package persistencia;



import hibernate.HibernateUtil;
import java.sql.SQLException;
import org.hibernate.criterion.*;
import org.hibernate.*;
import org.hibernate.SQLQuery.*;
import java.util.*;
import org.hibernate.exception.ConstraintViolationException;

public class DAO {

    private Session session = null;
    private final Class classe;
    private Transaction tx;

    public DAO(Class classe) {
        this.setSession(HibernateUtil.getInstance());
        this.classe = classe;
        this.tx = null;
        this.session.flush();
    }

    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }

    public boolean incluir(Object objeto) throws Exception,ConstraintViolationException{
        try {
            tx = getSession().beginTransaction();
            this.getSession().save(objeto);
            tx.commit();
            return true;
        }catch(ConstraintViolationException c){        
            tx.rollback();
            throw new ConstraintViolationException("CosntraintViolationException",new SQLException(),"erro constraint");
        } catch (Exception e) {
            System.err.println("Erro:" + e.getMessage());
            tx.rollback();
            throw new Exception(e.getMessage(),e);
        }//fim catch
        finally {
            this.getSession().close();
        }
    }//fim incluir

    public boolean excluir(Object objeto)throws Exception {
           try {
            tx = getSession().beginTransaction();
            getSession().delete(objeto);
            tx.commit();         
            return true;
        } catch (Exception e) {
            System.err.println("Erro:" + e.getMessage());
            tx.rollback();
            throw new Exception(e.getMessage(),e);
        }//fim catch
        finally {
            this.getSession().close();
        }
    }//fim excluir

    public boolean atualizar(Object objeto) throws Exception {
        try {
            tx = getSession().beginTransaction();
            getSession().merge(objeto);
            getSession().flush();
            tx.commit();          
            return true;
         }catch (org.hibernate.StaleStateException ex) {
            tx.rollback();
            throw new Exception(ex.getMessage(),ex);
        } catch (Exception e) {
            System.err.println("Erro:" + e.getMessage());
            tx.rollback();
            throw new Exception(e.getMessage(),e);
        }//fim catch
        finally {
            this.getSession().close();
        }
    }//fim update
    //busca para efetuar o login

   public List buscaNome(CriterioBusca criterios) {
        //em ordem crescente do criterio
        try {
            this.setSession(HibernateUtil.getInstance());
            Criteria busca = getSession().createCriteria(this.classe);
            busca.add(Restrictions.ilike(criterios.getCriterioBusca(), "%"+criterios.getValor()+"%".toString()))
                    .add(Restrictions.eq("ativo", true));
            busca.addOrder(Order.asc(criterios.getCriterioBusca()));
            return busca.list();
       } catch (NullPointerException ex) {
         System.err.println("Ocorreu um erro" + ex.getMessage());
         return null;
        } catch(Exception e) {
            System.err.println("Ocorreu um erro:" + e.getMessage());
            return null;
        }finally {
           this.getSession().close();
        }
    }//fim busca


    public List buscaComPaginacao(CriterioBusca criterios, int firstResult, int maxResult) {
        //em ordem crescente do criterio
        try {
            Criteria busca = getSession().createCriteria(this.classe);
            busca.add(Restrictions.ilike(criterios.getCriterioBusca(), criterios.getValor().toString())).add(Restrictions.eq("ativo", true));
            busca.addOrder(Order.asc(criterios.getCriterioBusca())).setFirstResult(firstResult).setMaxResults(maxResult);
            return busca.list();
        } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
        } catch (Exception e) {
            System.err.println("Ocorreu um erro:" + e.getMessage());
            return null;
        }finally {
            this.getSession().close();
        }
    }//fim busca

    //busca todos registros com ordenacao determinada pelo usuario
    public List buscarTodos(String ordenarPor) {
      try{
        List t = this.getSession().createCriteria(this.classe)
                .add(Restrictions.eq("ativo", true)) //filtra: apenas os ativos
                .addOrder(Order.asc(ordenarPor)).list();//ordena a lista
        return t;
      } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
      }catch(Exception e){
           System.err.println("Ocorreu um erro" + e.getMessage());
             return null;
      }finally{
            this.getSession().close();
      }
    }//fim lista tudo

    public List buscarTodosComPaginacao(int firstResult, int maxResult,String ordenarPor) {
       try{
        List t = this.getSession().createCriteria(this.classe)
                .setFirstResult(firstResult).setMaxResults(maxResult)
                 .add(Restrictions.eq("ativo", true))
                 .addOrder(Order.asc(ordenarPor)).list();
        return t;
       } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
       }catch(Exception e){
         System.out.println("Erro na busca com paginação: "+e.getMessage()+ e.getStackTrace());
         return null;
       }finally {
           this.getSession().close(); }
    }//fim lista tudo

        //busca todos registros com ordenacao determinada pelo usuario
    public List buscarTodosComAssociacaoECriterios(String ordenarPor,String nomeObjetoAssociado,
        CriterioBusca criterio) {
      try{
        List t = this.getSession().createCriteria(this.classe)
                .add(Restrictions.eq("ativo", true)) //filtra: apenas os ativos
                 .addOrder(Order.asc(ordenarPor))
                .createCriteria(nomeObjetoAssociado)
                .add(Restrictions.eq(criterio.getCriterioBusca(),criterio.getValor())).list();
               
       return t;
      } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
      }catch(Exception e){
           System.err.println("Ocorreu um erro" + e.getMessage());
             return null;
      }finally{
            this.getSession().close();
      }
    }//fim lista tudo


          //busca todos registros com ordenacao determinada pelo usuario
    public List buscarTodosComAssociacaoSemCriterios(String ordenarPor,String nomeObjetoAssociado){
      try{
        List t = this.getSession().createCriteria(this.classe)
                .add(Restrictions.eq("ativo", true)) //filtra: apenas os ativos
                 .addOrder(Order.asc(ordenarPor))
                .createCriteria(nomeObjetoAssociado).list();


                //.addOrder(Order.asc(ordenarPor)).list();//ordena a lista
        return t;
      } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
      }catch(Exception e){
           System.err.println("Ocorreu um erro" + e.getMessage());
             return null;
      }finally{
            this.getSession().close();
      }
    }//fim lista tudo








    //busca com projection e devolve o total de registros(linhas)
    public List buscarCodigo(CriterioBusca criterios) {
        try {
            Criteria busca = getSession().createCriteria(this.classe)
                    .add(Restrictions.eq(criterios.getCriterioBusca(), criterios.getValor()))
                     .add(Restrictions.eq("ativo", true));
            List it = busca.list();
            return it;
        } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro" + ex.getMessage());
             return null;
        } catch (Exception e) {
            System.err.println("Ocorreu um erro:" + e.getMessage());
            return null;
        }finally{
           this.getSession().close();
        }
    }//busca funcionando por codido

    public int buscaTotalRegistros() {
      try{
        int valorRetorno = 0;
        Criteria busca = getSession().createCriteria(this.classe).setProjection(Projections.rowCount());
        List lista = busca.list();
        if(lista.isEmpty()){
            valorRetorno = 0;
        }else{
         Iterator aux = busca.list().iterator();
         valorRetorno = Integer.parseInt(aux.next().toString());
       }//fim else
        return valorRetorno;
      } catch (NullPointerException ex) {
         System.err.println("Ocorreu um erro" + ex.getMessage());
         return 0;
      }catch(Exception e){
          System.err.println("Ocorreu um erro:" + e.getMessage());
          return 0;
      }finally {
            this.getSession().close();
        }
    }//busca funcionando = total de registros(rows)

    //criterio de busca o item a ser feito o join
    public List buscaComAssociacao(CriterioBusca criterios, String nomeObjetoAssociado) {
       try {
         Criteria busca = getSession().createCriteria(this.classe).createCriteria(nomeObjetoAssociado)
                 .add(Restrictions.ilike(criterios.getCriterioBusca(),criterios.getValor()))
                  .add(Restrictions.eq("ativo", true));
         return busca.list();
       } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro na busca com associação:" + ex.getMessage());
             return null;
        }catch (Exception e ){
            System.err.println("Erro na consulta. Excecao:" + e.getMessage());
            return null;
        } finally {
            this.getSession().close();
        }
    }//fim busca com associacao

    public List buscaComAssociacaoSemCriterio(String nomeObjetoAssociado){
        try {
         Criteria busca = getSession().createCriteria(this.classe).createCriteria(nomeObjetoAssociado)
                  .add(Restrictions.eq("ativo", true));
         return busca.list();
       } catch (NullPointerException ex) {
             System.err.println("Ocorreu um erro na busca com associação sem criterio:" + ex.getMessage());
             return null;
        }catch (Exception e ){
            System.err.println("Erro na consulta. Excecao:" + e.getMessage());
            return null;
        }finally {
            this.getSession().close();
        }
    }


    public List buscaComItem(String nomeObjetoAssociado){
       try {
            Criteria busca = getSession().createCriteria(this.classe).createCriteria("chaveComposta").
                   createCriteria(nomeObjetoAssociado);
            return busca.list();
       }catch (Exception e ){
            System.err.println("Erro na consulta. Excecao:" + e.getMessage());
            return null;
        }finally {
            this.getSession().close();
        }
    }

}//fim class







